#include "stdafx.h"
#include "EssNetworkPCH.h"
#include "EssConnector.h"
#include "EssNetworkHelper.h"
#include "..\Utils\Debug.h"

EssConnector::EssConnector()
{

}

EssConnector::EssConnector(SOCKET s) : EssPeer(s)
{

}

EssConnector::~EssConnector()
{
	_clearSendBuffers();
}

bool EssConnector::connectSock(HWND wnd, UINT message, const char* ip, u_short port)
{
	sockaddr_in dest;
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = EssNetworkHelper::getIPAddress(ip);
	dest.sin_port = htons(port);

	if (WSAAsyncSelect(mSocket, wnd, message, FD_CONNECT) == SOCKET_ERROR)
	{
		TRACE("WSAAsyncSelect(mSocket, wnd, message, FD_CONNECT) == SOCKET_ERROR errorCode=%d.\n", WSAGetLastError());
		return false;
	}

	if (::connect(mSocket, (const sockaddr*)&dest, sizeof(dest)) == SOCKET_ERROR)
	{
		if (WSAGetLastError() != WSAEWOULDBLOCK)
		{
			return false;
		}
	}

	return true;
}

bool EssConnector::isConnected()
{
	if (::send(mSocket, 0, 0, 0) == SOCKET_ERROR)
	{
		if (WSAGetLastError() != WSAEWOULDBLOCK)
		{
			return false;
		}
	}
	return true;
}

bool EssConnector::sendSock(const char* buf, int len, int flags /* = 0 */)
{
	if (_dispatchSendBuffers())
	{
		if (::send(mSocket, buf, len, flags) != SOCKET_ERROR)
		{
			return true;
		}
		else
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)
			{
				return false;
			}
		}
	}

	PacketBuffer* packet = new PacketBuffer;
	packet->flags = flags;
	packet->buf.push((const void*)buf, len);
	mSendBuffer.push(packet);

	return true;
}

bool EssConnector::_dispatchSendBuffers()
{
	while(!mSendBuffer.empty())
	{
		PacketBuffer* packet = mSendBuffer.front();
		if (::send(mSocket, (const char*)packet->buf.base(), packet->buf.size(), packet->flags) != SOCKET_ERROR)
		{
			delete packet;
			mSendBuffer.pop();
		}
		else
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)
			{
				_clearSendBuffers();
			}
			return false;
		}
	}

	return true;
}

void EssConnector::_clearSendBuffers()
{
	while(!mSendBuffer.empty())
	{
		delete mSendBuffer.front();
		mSendBuffer.pop();
	}
}

int EssConnector::recv()
{
#define RECV_BUFFER_SIZE	1024
	int total = 0;
	while (true)
	{
		char tmp[RECV_BUFFER_SIZE];
		int bytes = ::recv(mSocket, tmp, RECV_BUFFER_SIZE, 0);
		if (bytes <= 0)
		{
			break;
		}
		else
		{
			mRecvBuffer.push((const void*)tmp, bytes);
			total += bytes;
		}
	}
	return total;
}

EssBuffer& EssConnector::getRecvBuffer()
{
	return mRecvBuffer;
}

void EssConnector::_clearRecvBuffer()
{
	mRecvBuffer.clear();
}